home *** CD-ROM | disk | FTP | other *** search
- #include <errno.h>
- #include <fcntl.h>
- #include <newt.h>
- #include <rpmlib.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/stat.h> /* for mkdir(2) ?!? */
- #include <sys/time.h>
- #include <sys/wait.h>
- #include <unistd.h>
-
- #include "config.h"
- #include "doit.h"
- #include "install.h"
- #include "kbd.h"
- #include "log.h"
- #include "windows.h"
-
- extern int testing;
- FILE * logFile = NULL;
-
- static int installPackage(rpmdb db, struct installMethod * method,
- struct packageInfo * pkg, int isPreskel,
- int errfd, char * netSharedPath, int flags);
- static void setupXfree(struct installMethod * method, rpmdb db,
- struct pkgSet * psp, char * netSharedPath, int errfd);
- static void setupXmetro(struct installMethod * method, rpmdb db,
- struct packageInfo * pkg, char * netSharedPath,
- int errfd);
- static void setupX(struct installMethod * method, rpmdb db,
- struct pkgSet * psp, char * netSharedPath, int errfd);
- static void rpmerror(void);
-
- static void swOpen(int numPackages, int sizePackages);
- static void swPackage(Header h);
- static void swPackageComplete();
- static void swClose(void);
- static void swCallback(const unsigned long amount, const unsigned long total);
- static void formatTime(char * buf, time_t t);
-
- static int installCpioArchive(struct installMethod * method, char * name,
- char * logFileName) {
- char * realName;
- char cmd[500];
- int olderrno;
- int rc;
-
- if (method->getFile(method, name, &realName, 1)) {
- if (logFile)
- fprintf(logFile, "Failed to get cpio archive %s.\n", name);
- return INST_ERROR;
- }
-
- chdir("/mnt");
- sprintf(cmd, "gunzip < %s | cpio -iumd --quiet 2>%s >%s",
- realName, logFileName, logFileName);
-
- logMessage("running: \"%s\"", cmd);
-
- if (testing) {
- messageWindow("would run: %s", cmd);
- return 0;
- }
-
- rc = system(cmd);
-
- if (rc) {
- olderrno = errno;
- logMessage(" command failed: %s rc = %d\n", strerror(olderrno), rc);
- olderrno = errno;
- errorWindow("error unpacking archive: %s");
-
- if (method->rmFiles) unlink(realName);
-
- return INST_ERROR;
- }
-
- if (method->rmFiles) unlink(realName);
-
- return 0;
- }
-
- int doInstall(struct installMethod * method, struct component * preskel,
- struct pkgSet * psp, char * netSharedPath, char * keymap,
- int upgrade) {
- int i, totalNumPackages, totalSizePackages;
- int flags = 0;
- rpmdb db;
- int errfd;
- char * logFileName = "/dev/tty5";
-
- mkdir("/mnt/tmp", 0755);
- mkdir("/mnt/var", 0755);
- mkdir("/mnt/var/lib", 0755);
- mkdir("/mnt/var/lib/rpm", 0755);
-
- if (upgrade) {
- flags |= RPMINSTALL_UPGRADE | RPMINSTALL_REPLACEFILES;
- logFile = fopen("/mnt/tmp/upgrade.log", "w");
- } else
- logFile = fopen("/mnt/tmp/install.log", "w");
- if (logFile) {
- setlinebuf(logFile);
- if (upgrade) {
- logMessage("opened /mnt/tmp/upgrade.log");
- } else {
- logMessage("opened /mnt/tmp/install.log");
- }
- } else {
- if (upgrade) {
- logMessage("failed to open /mnt/tmp/upgrade.log :-(");
- errorWindow("Failed to open /mnt/tmp/upgrade.log. No upgrade log "
- "will be kept.");
- } else {
- logMessage("failed to open /mnt/tmp/install.log :-(");
- errorWindow("Failed to open /mnt/tmp/install.log. No install log "
- "will be kept.");
- }
- }
-
- errfd = open(logFileName, O_APPEND | O_CREAT, 0644);
- if (errfd < 0) {
- logMessage("failed to open /dev/tty5!");
- logFileName = "/tmp/exec.log";
- errfd = open(logFileName, O_APPEND | O_CREAT, 0644);
- if (errfd < 0) {
- logMessage("failed to open %s: %s!\n", logFileName,
- strerror(errno));
- errfd = 2;
- }
- }
-
- rpmErrorSetCallback(rpmerror);
-
- logMessage("reading /usr/lib/rpmrc");
- rpmReadConfigFiles(NULL, NULL, NULL, 0);
- logMessage("\tdone");
-
- if (testing) {
- messageWindow("Status", "Packages would be installed now");
- return 0;
- }
-
- if (rpmdbOpen("/mnt", &db, O_RDWR | O_CREAT, 0644)) {
- errorWindow("Fatal error opening RPM database");
- return INST_ERROR;
- }
- logMessage("opened rpm database");
-
- /* It's safer to *always* install the base system */
- winStatus(45, 3, "Base system", "Installing base system...");
-
- if (installCpioArchive(method, "skeleton.cgz", logFileName))
- return INST_ERROR;
-
- newtPopWindow();
-
- logMessage("installing initial packages (%d of them)",
- preskel->ps.numPackages);
-
- totalNumPackages = 0, totalSizePackages = 0;
- for (i = 0; i < psp->numPackages; i++) {
- if (psp->packages[i]->selected) {
- totalSizePackages += psp->packages[i]->size;
- totalNumPackages++;
- }
- }
-
- swOpen(totalNumPackages, totalSizePackages);
-
- for (i = 0; i < preskel->ps.numPackages; i++) {
- if (!preskel->ps.packages[i]->selected) continue;
- logMessage(" installing %s", preskel->ps.packages[i]->name);
- installPackage(db, method, preskel->ps.packages[i], 1, errfd,
- netSharedPath, flags);
- preskel->ps.packages[i]->selected = 0; /* don't install it later */
- }
-
- #ifndef __sparc__
- mkdir("/mnt/etc/sysconfig", 0755);
- writeKbdConfig("/mnt/etc/sysconfig", keymap);
- #endif
-
- logMessage("installing packages");
- for (i = 0; i < psp->numPackages; i++) {
- if (!psp->packages[i]->selected) continue;
- installPackage(db, method, psp->packages[i], 0, errfd,
- netSharedPath, flags);
- }
- swClose();
-
- if (!upgrade) {
- mouseConfig();
- setupX(method, db, psp, netSharedPath, errfd);
- }
-
- rpmdbClose(db);
- close(errfd);
-
- if (logFile) fclose(logFile);
-
- logMessage("rpm database closed");
-
- return 0;
- }
-
- static int installPackage(rpmdb db, struct installMethod * method,
- struct packageInfo * pkg, int isPreskel,
- int errfd, char * netSharedPath, int flags) {
- int fd, olderr;
- char * realName;
- int olderrno, rc;
-
- if (flags & RPMINSTALL_UPGRADE) {
- if (logFile)
- fprintf(logFile, "Upgrading %s.\n", pkg->name);
- } else {
- if (logFile)
- fprintf(logFile, "Installing %s.\n", pkg->name);
- }
-
- swPackage(pkg->h);
-
- if (method->getFile(method, pkg->data, &realName, isPreskel)) {
- logMessage("getFile method failed for %s", pkg->data);
- if (logFile)
- fprintf(logFile, "Failed to get file for package %s.\n", pkg->name);
- swPackageComplete();
- return 1;
- }
-
- fd = open(realName, O_RDONLY);
- if (fd < 0) {
- olderrno = errno;
- logMessage("cannot open RPM file %s: %s", pkg->data,
- strerror(olderrno));
- messageWindow("Error", "Error installing package: cannot open RPM file "
- "for %s: %s", pkg->data, strerror(errno));
- if (logFile)
- fprintf(logFile, "\tcannot open RPM file %s: %s\n",
- (char *) pkg->data, strerror(olderrno));
-
- swPackageComplete();
-
- return 1;
- }
-
- olderr = dup(2);
- dup2(errfd, 2);
- rc = rpmInstallPackage("/mnt", db, fd, NULL,
- flags | RPMINSTALL_REPLACEPKG | RPMINSTALL_REPLACEFILES,
- swCallback, NULL, netSharedPath);
- dup2(olderr, 2);
- close(olderr);
-
- if (rc) {
- olderrno = errno;
- logMessage("Error installing package: package install of "
- "%s failed: %s", pkg->name, rpmErrorString());
- messageWindow("Error", "RPM install of %s failed: %s", pkg->name,
- rpmErrorString());
- if (logFile)
- fprintf(logFile, "\tcannot open RPM file %s: %s\n",
- (char *) pkg->data, strerror(olderrno));
- }
-
- close(fd);
- swPackageComplete();
-
- if (method->rmFiles) unlink(realName);
-
- return 0;
- }
-
- static void setupX(struct installMethod * method, rpmdb db,
- struct pkgSet * psp, char * netSharedPath, int errfd) {
- int hasMetro = 0, i;
- newtComponent text, yes, no, form, answer;
- struct packageInfo * metroPackage = NULL;
-
- /* This is a cheap trick to see if our X component was installed */
- if (access("/mnt/usr/X11R6/bin/Xconfigurator", X_OK)) {
- logMessage("/mnt/usr/X11R6/bin/Xconfigurator cannot be run");
- return;
- }
-
- logMessage("looking for metrox");
- for (i = 0; i < psp->numPackages; i++) {
- if (!strcmp(psp->packages[i]->name, "metroess")) {
- logMessage("\tfound metrolink!");
- metroPackage = psp->packages[i];
- hasMetro = 1;
- break;
- }
- }
-
- if (!hasMetro)
- return setupXfree(method, db, psp, netSharedPath, errfd);
-
- newtOpenWindow(10, 4, 60, 16, "Metro-X");
-
- text = newtTextbox(1, 1, 58, 9, NEWT_TEXTBOX_WRAP);
- newtTextboxSetText(text,
- "This copy of Red Hat Linux includes MetroX from MetroLink.\n\n"
- "MetroX is LICENSED SOFTWARE. Your purchase of Red Hat Linux "
- "entitles you to one (1) user license for this software. You "
- "may not install and run MetroX on more than one computer "
- "without purchasing additional licenses, which are available "
- "from Red Hat Software (800) 454-5502. Would you like to install "
- "MetroX on your computer?");
- yes = newtButton(13, 12, "Yes");
- no = newtButton(36, 12, "No");
-
- form = newtForm(NULL, NULL, 0);
- newtFormAddComponents(form, text, yes, no, NULL);
-
- newtRunForm(form);
- answer = newtFormGetCurrent(form);
-
- newtFormDestroy(form);
- newtPopWindow();
-
- if (answer == yes) {
- setupXmetro(method, db, metroPackage, netSharedPath, errfd);
- } else {
- setupXfree(method, db, psp, netSharedPath, errfd);
- }
- }
-
- static void setupXmetro(struct installMethod * method, rpmdb db,
- struct packageInfo * pkg, char * netSharedPath,
- int errfd) {
- int childpid;
- int status;
-
- swOpen(1, pkg->size);
- installPackage(db, method, pkg, 0, errfd, netSharedPath, 0);
- swClose();
-
- symlink("../../usr/X11R6/bin/Xmetro", "/mnt/etc/X11/X");
-
- newtSuspend();
- if (!(childpid = fork())) {
- chroot("/mnt");
- putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin");
- chdir("/");
- execl("/usr/X11R6/bin/configX", "/usr/X11R6/bin/configX", NULL);
- }
-
- waitpid(childpid, &status, 0);
-
- newtResume();
- }
-
- static void setupXfree(struct installMethod * method, rpmdb db,
- struct pkgSet * psp, char * netSharedPath, int errfd) {
- int childpid;
- int status;
- int fd, i;
- char buf[200], * chptr;
- char server[50];
-
- newtSuspend();
- if (!(childpid = fork())) {
- chroot("/mnt");
- putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin");
- chdir("/");
- execl("/usr/X11R6/bin/Xconfigurator", "/usr/X11R6/bin/Xconfigurator",
- "--pick", NULL);
- }
-
- waitpid(childpid, &status, 0);
-
- newtResume();
-
- if ((fd = open("/mnt/tmp/SERVER", O_RDONLY)) < 0) {
- logMessage("failed to open /mnt/tmp/SERVER: %s", strerror(errno));
- return;
- }
-
- buf[0] = '\0';
- read(fd, buf, sizeof(buf));
- close(fd);
- chptr = buf;
- while (chptr < (buf + sizeof(buf) - 1) && *chptr && *chptr != ' ')
- chptr++;
-
- if (chptr >= (buf + sizeof(buf) - 1) || *chptr != ' ') {
- logMessage("couldn't find ' ' in /mnt/tmp/SERVER");
- return;
- }
-
- *chptr = '\0';
- strcpy(server, "XFree86-");
- strcat(server, buf);
-
- logMessage("I will install the %s package", server);
-
- for (i = 0; i < psp->numPackages; i++) {
- if (!strcmp(psp->packages[i]->name, server)) {
- logMessage("\tfound package: %s", psp->packages[i]->name);
- swOpen(1, psp->packages[i]->size);
- installPackage(db, method, psp->packages[i], 0, errfd,
- netSharedPath, 0);
- swClose();
- break;
- }
- }
-
- newtSuspend();
- if (!(childpid = fork())) {
- chroot("/mnt");
- chdir("/");
- execl("/usr/X11R6/bin/Xconfigurator", "/usr/X11R6/bin/Xconfigurator",
- "--continue", NULL);
- }
-
- waitpid(childpid, &status, 0);
-
- newtResume();
- }
-
- static void rpmerror(void) {
- int code;
-
- code = rpmErrorCode();
- if (code != RPMERR_UNLINK && code != RPMERR_RMDIR) {
- if (logFile)
- fprintf(logFile, "%s\n", rpmErrorString());
- else
- logMessage(rpmErrorString());
- }
- }
-
- static struct statusWindowInfo {
- newtComponent form, packageLabel, sizeLabel, summaryText;
- newtComponent pkgScale, globalScale;
- newtComponent pkgDoneLabel, pkgRemainsLabel;
- newtComponent sizeDoneLabel, sizeRemainsLabel;
- newtComponent timeDoneLabel, timeRemainsLabel, timeTotalLabel;
- int numPackages, packagesDone;
- unsigned int sizePackages, sizeDone;
- int thisPackageSize;
- time_t timeStarted;
- } si;
-
- static void swOpen(int numPackages, int sizePackages) {
- char buf[50];
-
- newtOpenWindow(10, 4, 60, 15, "Install Status");
-
- si.form = newtForm(NULL, NULL, 0);
- newtFormAddComponent(si.form, newtLabel(1, 1, "Package:"));
- newtFormAddComponent(si.form, newtLabel(1, 2, "Size :"));
- newtFormAddComponent(si.form, newtLabel(1, 3, "Summary:"));
-
- si.packageLabel = newtLabel(13, 1, "");
- si.sizeLabel = newtLabel(13, 2, "");
- si.summaryText = newtTextbox(13, 3, 45, 2, NEWT_TEXTBOX_WRAP);
-
- si.pkgScale = newtScale(3, 6, 54, 100);
-
- newtFormAddComponent(si.form,
- newtLabel(1, 8, " Packages Bytes Time"));
- /* 12345678901234567890123456789012345678901234567
- 1 2 3 4 */
- newtFormAddComponent(si.form, newtLabel(1, 9, "Total :"));
- newtFormAddComponent(si.form, newtLabel(1, 10, "Completed :"));
- newtFormAddComponent(si.form, newtLabel(1, 11, "Remaining :"));
-
- si.numPackages = numPackages;
- si.sizePackages = sizePackages;
- si.packagesDone = 0;
- si.sizeDone = 0;
- si.timeStarted = time(NULL);
-
- sprintf(buf, "%8d", numPackages);
- newtFormAddComponent(si.form, newtLabel(14, 9, buf));
- si.pkgDoneLabel = newtLabel(14, 10, "");
- si.pkgRemainsLabel = newtLabel(14, 11, "");
-
- sprintf(buf, "%4uM", sizePackages / (1024 * 1024));
- newtFormAddComponent(si.form, newtLabel(29, 9, buf));
- si.sizeDoneLabel = newtLabel(29, 10, "");
- si.sizeRemainsLabel = newtLabel(29, 11, "");
-
- si.timeTotalLabel = newtLabel(42, 9, "");
- si.timeDoneLabel = newtLabel(42, 10, "");
- si.timeRemainsLabel = newtLabel(42, 11, "");
-
- si.globalScale = newtScale(1, 13, 58, sizePackages);
-
- newtFormAddComponents(si.form, si.packageLabel, si.sizeLabel,
- si.summaryText, si.pkgScale, si.globalScale,
- si.pkgDoneLabel, si.pkgRemainsLabel,
- si.sizeDoneLabel, si.sizeRemainsLabel,
- si.timeDoneLabel, si.timeRemainsLabel,
- si.timeTotalLabel, NULL);
- }
-
- static void swPackage(Header h) {
- char * name, * version, * release, * summary;
- char buf[50];
- uint_32 * size;
-
- headerGetEntry(h, RPMTAG_NAME, NULL, (void *) &name, NULL);
- headerGetEntry(h, RPMTAG_VERSION, NULL, (void *) &version, NULL);
- headerGetEntry(h, RPMTAG_RELEASE, NULL, (void *) &release, NULL);
- headerGetEntry(h, RPMTAG_SIZE, NULL, (void *) &size, NULL);
-
- if (!headerGetEntry(h, RPMTAG_SUMMARY, NULL, (void *) &summary, NULL))
- summary = "(no summary)";
-
- sprintf(buf, "%s-%s-%s", name, version, release);
- newtLabelSetText(si.packageLabel, buf);
-
- sprintf(buf, "%dk", (*size) / 1024);
- newtLabelSetText(si.sizeLabel, buf);
-
- newtTextboxSetText(si.summaryText, summary);
-
- si.thisPackageSize = *size;
-
- newtScaleSet(si.pkgScale, 0);
-
- newtDrawForm(si.form);
- newtRefresh();
- }
-
- static void swPackageComplete(void) {
- char buf[50];
- time_t now, finishTime, elapsedTime, remainingTime;
-
- si.packagesDone++;
- si.sizeDone += si.thisPackageSize;
-
- sprintf(buf, "%8d", si.packagesDone);
- newtLabelSetText(si.pkgDoneLabel, buf);
-
- sprintf(buf, "%8d", si.numPackages - si.packagesDone);
- newtLabelSetText(si.pkgRemainsLabel, buf);
-
- sprintf(buf, "%4dM", si.sizeDone / (1024 * 1024));
- newtLabelSetText(si.sizeDoneLabel, buf);
-
- sprintf(buf, "%4dM", (si.sizePackages - si.sizeDone) / (1024 * 1024));
- newtLabelSetText(si.sizeRemainsLabel, buf);
-
- now = time(NULL);
- elapsedTime = now - si.timeStarted;
- formatTime(buf, elapsedTime);
- newtLabelSetText(si.timeDoneLabel, buf);
-
- finishTime = (((float) si.sizePackages) / si.sizeDone) * elapsedTime;
- formatTime(buf, finishTime);
- newtLabelSetText(si.timeTotalLabel, buf);
-
- remainingTime = finishTime - elapsedTime;
- formatTime(buf, remainingTime);
- newtLabelSetText(si.timeRemainsLabel, buf);
-
- newtScaleSet(si.globalScale, si.sizeDone);
-
- newtRefresh();
- }
-
- static void swCallback(const unsigned long amount, const unsigned long total) {
- if (total == 0)
- newtScaleSet(si.pkgScale, 100);
- else
- newtScaleSet(si.pkgScale, (amount * 100) / total);
-
- newtRefresh();
- }
-
- static void swClose(void) {
- newtPopWindow();
- }
-
- static void formatTime(char * buf, time_t t) {
- int hours, minutes, secs;
-
- hours = t / 60 / 60;
- t %= (60 * 60);
-
- minutes = t / 60;
- t %= 60;
-
- secs = t;
-
- sprintf(buf, "%01d:%02d.%02d", hours, minutes, secs);
- }
-